<template>
  <el-card shadow="hover" class="rd-8 mb-8">
    <el-input
      prefix-icon="Search"
      v-model="filterText"
      clearable
      placeholder="请输入课程分类标题"
    />
  </el-card>
  <el-card shadow="hover" class="rd-8">
    <template #header>
      <div class="flex flex-justify-between">
        <div>
          <el-button
            icon="Finished"
            type="primary"
            plain
            v-if="draggable"
            :disabled="updateNodes.length == 0"
            @click="batchSave"
          >
            批量保存
          </el-button>
          <el-button
            icon="Delete"
            type="danger"
            plain
            @click="batchDelete"
            :disabled="tids.length == 0"
          >
            批量删除
          </el-button>
          <el-button icon="Upload" type="success" plain @click="handleImport">
            批量上传
          </el-button>
        </div>
        <el-switch
          v-model="draggable"
          active-text="开启拖拽"
          inactive-text="关闭拖拽"
        ></el-switch>
      </div>
    </template>
    <el-tree
      style="--el-tree-node-content-height: 40px"
      ref="treeRef"
      :allow-drop="allowDrop"
      :data="data"
      node-key="subjectId"
      :draggable="draggable"
      :expand-on-click-node="false"
      :default-expanded-keys="expandedKey"
      show-checkbox
      :props="defaultProps"
      @check="handleCheck"
      @node-drop="handleDrop"
      :filter-node-method="filterNode"
    >
      <template #default="{ node, data }">
        <span class="custom-tree-node">
          <span>{{ node.label }}</span>
          <span>
            <el-button
              type="primary"
              icon="Plus"
              @click="append(data)"
              v-show="node.level != 2"
              size="small"
              text
              bg
            >
              添加
            </el-button>
            <el-button
              type="danger"
              icon="Delete"
              v-show="node.childNodes == 0"
              @click="remove(node, data)"
              size="small"
              text
              bg
            >
              删除
            </el-button>
            <el-button
              type="success"
              icon="Edit"
              @click="edit(data)"
              size="small"
              text
              bg
            >
              修改
            </el-button>
          </span>
        </span>
      </template>
    </el-tree>
  </el-card>
  <!-- 添加修改分类 -->
  <el-dialog
    v-model="dialog.visible"
    :title="dialog.title"
    width="700px"
    align-center
    append-to-body
  >
    <el-form :model="subjectForm" :rules="rules" ref="formRef">
      <el-form-item label="分类名称" prop="title">
        <el-input v-model="subjectForm.title" />
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="dialog.visible = false">取消</el-button>
        <el-button type="primary" @click="handleConfirm">确认</el-button>
      </span>
    </template>
  </el-dialog>

  <!-- 用户导入对话框 -->
  <el-dialog
    :title="upload.title"
    v-model="upload.open"
    width="400px"
    append-to-body
  >
    <el-upload
      ref="uploadRef"
      :limit="1"
      accept=".xlsx, .xls"
      :action="upload.url"
      :disabled="upload.isUploading"
      :on-progress="handleFileUploadProgress"
      :on-success="handleFileSuccess"
      :auto-upload="false"
      drag
    >
      <el-icon class="el-icon--upload">
        <upload-filled />
      </el-icon>
      <div class="el-upload__text">
        将文件拖到此处，或
        <em>点击上传</em>
      </div>
      <template #tip>
        <div class="text-center el-upload__tip">
          <span>仅允许导入xls、xlsx格式文件。</span>
          <el-link
            type="primary"
            :underline="false"
            style="font-size: 12px; vertical-align: baseline"
            :href="importTemplate"
          >
            下载模板
          </el-link>
        </div>
      </template>
    </el-upload>
    <template #footer>
      <div class="dialog-footer">
        <el-button type="primary" @click="submitFileForm">确 定</el-button>
        <el-button @click="upload.open = false">取 消</el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import importTemplate from '@/assets/template/user_template.xlsx'
import type Node from 'element-plus/es/components/tree/src/model/node'
import type {
  AllowDropType,
  NodeDropType,
} from 'element-plus/es/components/tree/src/tree.type'
import {
  reqSubjectTree,
  reqBatchDelSubject,
  reqUpdateDropSubject,
  reqDeleteSubject,
  reqAddSubject,
  reqUpdateSubject,
} from '@/api/subject'
import { ImportOption, Subject } from '@/api/subject/type'
import { ElTree } from 'element-plus'
import type {
  FormInstance,
  FormRules,
  UploadInstance,
  UploadFile,
} from 'element-plus'
import { ElMessageBox, ElMessage } from 'element-plus'
const treeRef = ref<InstanceType<typeof ElTree>>()
let draggable = ref<boolean>(true)

const formRef = ref<FormInstance>()
const uploadRef = ref<UploadInstance>()
let dialog = reactive<DialogOption>({
  visible: false,
  title: '',
  pid: undefined,
})
const rules = reactive<FormRules>({
  title: [
    { required: true, message: '名称不能为空', trigger: 'blur' },
    {
      min: 1,
      max: 10,
      message: '分类名称长度必须介于 1 和 10 之间',
      trigger: 'blur',
    },
  ],
})

const initForm: Subject = {
  subjectId: undefined,
  title: '',
  pid: '0',
  sort: 0,
  delFlag: '0',
}
let subjectForm = ref<Subject>({ ...initForm })
//append edit remove
const edit = (data: Subject) => {
  formRef.value?.clearValidate()
  //清空
  dialog.visible = true
  dialog.title = '修改分类'
  subjectForm.value = { subjectId: data.subjectId, title: data.title }
  expandedKeyPid.value.push(data.subjectId as string)
}
const append = (data: Subject) => {
  dialog.pid = data.subjectId
  formRef.value?.clearValidate()
  //清空
  subjectForm.value = { ...initForm }
  //赋值当前节前节点
  dialog.visible = true
  dialog.title = '添加分类'
  //展开当前节点
  expandedKeyPid.value.push(data.subjectId as string)
}
const handleConfirm = async () => {
  if (subjectForm.value.subjectId) {
    await reqUpdateSubject(subjectForm.value)
  } else {
    subjectForm.value.pid = dialog.pid
    await reqAddSubject(subjectForm.value)
  }
  ElMessage.success('操作成功')
  dialog.visible = false
  expandedKey.value = expandedKeyPid.value
  await getTree()
}
const remove = async (node: Node, data: Subject) => {
  try {
    await ElMessageBox.confirm(`是否批量删除【${data.title}】菜单?`, '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
    })
    expandedKeyPid.value.push(node.parent.data.subjectId)
    await reqDeleteSubject(data.subjectId as string)
    ElMessage.success('删除成功')
    expandedKey.value = expandedKeyPid.value
    await getTree()
  } catch (error) {
    return
  }
}
//搜索
const filterText = ref('')
watch(filterText, (val) => {
  treeRef.value?.filter(val)
})
//过滤
const filterNode = (
  value: string,
  data: {
    [key: string]: any
  },
) => {
  if (!value) return true
  return data.title.includes(value)
}

const defaultProps = {
  children: 'children',
  label: 'title',
}

const data = ref([])

const getTree = async () => {
  let result = await reqSubjectTree()
  data.value = result.data
  // console.log(result.data)
}
let expandedKeyPid = ref<string[]>([])
let expandedKey = ref<string[]>([])
//保存
const batchSave = async () => {
  await reqUpdateDropSubject(updateNodes.value)
  ElMessage.success('分类顺序等修改成功')
  maxLevel = 0
  updateNodes.value = []
  expandedKey.value = expandedKeyPid.value
  await getTree()
}

//删除
const batchDelete = async () => {
  try {
    await ElMessageBox.confirm(`是否批量删除【${tids.value}】菜单?`, '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
    })
    await reqBatchDelSubject(tids.value)
    ElMessage.success('批量删除成功')
    tids.value = []
    expandedKey.value = expandedKeyPid.value
    await getTree()
  } catch (error) {
    return
  }
}

onMounted(() => {
  getTree()
})
let updateNodes = ref<Subject[]>([])
/* 拖拽API */
/* 待删除id数组 */
let tids = ref<string[]>([])
const handleCheck = (_: any, treeStatus: any) => {
  tids.value = treeStatus.checkedKeys
  expandedKeyPid.value.push(...treeStatus.halfCheckedKeys)
}
/* 拖拽成功完成时触发的事件 */
const handleDrop = (
  draggingNode: Node,
  dropNode: Node,
  dropType: NodeDropType,
) => {
  // console.log('tree drop:', dropNode.label, dropType)
  //1、当前节点最新的父节点id
  let pid = '0'
  let siblings = null
  if (dropType == 'before' || dropType == 'after') {
    pid =
      dropNode.parent.data.subjectId == undefined
        ? '0'
        : dropNode.parent.data.subjectId
    siblings = dropNode.parent.childNodes
  } else {
    pid = dropNode.data.subjectId
    siblings = dropNode.childNodes
  }
  expandedKeyPid.value.push(pid)
  //2、当前拖拽节点的最新顺序，
  for (let i = 0; i < siblings.length; i++) {
    if (siblings[i].data.subjectId == draggingNode.data.subjectId) {
      //如果遍历的是当前正在拖拽的节点
      updateNodes.value.push({
        subjectId: siblings[i].data.subjectId,
        sort: i,
        pid: pid,
      })
    } else {
      updateNodes.value.push({ subjectId: siblings[i].data.subjectId, sort: i })
    }
  }
}
//最深层级
let maxLevel = 0
let minLevel = 0
/* 拖拽时判定目标节点能否成为拖动目标位置 */
const allowDrop = (draggingNode: Node, dropNode: Node, type: AllowDropType) => {
  maxLevel = draggingNode.level
  minLevel = draggingNode.level
  //当前节点不能大于3
  countNodeLevel(draggingNode)
  //1）、被拖动的当前节点总层数
  let deep = Math.abs(maxLevel - minLevel) + 1
  return type == 'inner'
    ? deep + dropNode.level <= 2
    : deep + dropNode.parent.level <= 2
}

//查询所有子节点
const countNodeLevel = (node: Node) => {
  if (node.childNodes != null && node.childNodes.length > 0) {
    for (let i = 0; i < node.childNodes.length; i++) {
      maxLevel =
        node.childNodes[i].level > minLevel
          ? node.childNodes[i].level
          : minLevel
      countNodeLevel(node.childNodes[i])
    }
  }
}

/*** 用户导入参数 */
const upload = reactive<ImportOption>({
  // 是否显示弹出层（用户导入）
  open: false,
  // 弹出层标题（用户导入）
  title: '',
  // 是否禁用上传
  isUploading: false,
  // 是否更新已经存在的用户数据
  updateSupport: 0,
  // 上传的地址
  url: import.meta.env.VITE_APP_BASE_API + '/subject/importData',
})

/** 导入按钮操作 */
const handleImport = () => {
  upload.title = '用户导入'
  upload.open = true
}
/**文件上传中处理 */
const handleFileUploadProgress = () => {
  upload.isUploading = true
}
/** 文件上传成功处理 */
const handleFileSuccess = (response: any, file: UploadFile) => {
  upload.open = false
  upload.isUploading = false
  uploadRef.value?.handleRemove(file)
  ElMessageBox.alert(
    "<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" +
      response.data +
      '</div>',
    '导入结果',
    { dangerouslyUseHTMLString: true },
  )
  getTree()
}

/** 提交上传文件 */
function submitFileForm() {
  uploadRef.value?.submit()
}
</script>

<style lang="scss" scoped>
.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}
</style>
